#include <iostream>
using namespace std;

#include "den_query.h"

#include<cassert>

namespace Den{


namespace{
namespace Meta{

//сборник compile-time алгоритмов
//--------------ассерт времени компиляции с++03---------------//
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define LOKI_STATIC_CHECK(expr, msg) { Meta::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } 
//------------------------------------------------------------//

//------------------не существующий тип данных. нет даже void--------------//
struct SEmpty{};
//------------------------------------------------------------------------//

//------------ если флаг true - выберет T, иначе U ----------------------------//
template <bool FLAG, typename T, typename U> struct Select { typedef T Result; };
template <typename T, typename U> struct Select<false, T, U> { typedef U Result; };
//------------------------------------------------------------------------//

//---------- выберет тип с максимальным sizeof
template<class T1, class T2, class T3=SEmpty, class T4=SEmpty, class T5=SEmpty, 
         class T6=SEmpty, class T7=SEmpty, class T8=SEmpty, class T9=SEmpty, class T10=SEmpty>
struct SelectMax
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Result ,T10>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
struct SelectMax<T1,T2,T3,T4,T5,T6,T7,T8,T9,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4,T5,T6,T7,T8>::Result ,T9>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4,class T5,class T6,class T7,class T8>
struct SelectMax<T1,T2,T3,T4,T5,T6,T7,T8,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4,T5,T6,T7>::Result ,T8>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4,class T5,class T6,class T7>
struct SelectMax<T1,T2,T3,T4,T5,T6,T7,SEmpty,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4,T5,T6>::Result ,T7>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4,class T5,class T6>
struct SelectMax<T1,T2,T3,T4,T5,T6,SEmpty,SEmpty,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4,T5>::Result ,T6>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4,class T5>
struct SelectMax<T1,T2,T3,T4,T5,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3,T4>::Result ,T5>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3,class T4>
struct SelectMax<T1,T2,T3,T4,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2,T3>::Result ,T4>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2,class T3>
struct SelectMax<T1,T2,T3,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty>
{
	typedef typename SelectMax< typename SelectMax<T1,T2>::Result ,T3>::Result Result;
	enum { eSIZE = sizeof(Result) };
};
template<class T1, class T2>struct SelectMax<T1,T2,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty,SEmpty>
{
	enum { eFIRST_IF_TRUE = sizeof(T1)>sizeof(T2) };
	typedef typename Select<eFIRST_IF_TRUE,T1,T2>::Result Result;
	enum { eSIZE = sizeof(Result) };
};

}//namespace Meta

enum eTYPE{ eNULL, eBOOL, eINT, eDOUBLE, eSTRING, eVECTOR, eMAP };
typedef QueryTypes::Str Str;
typedef QueryTypes::Vec Vec;
typedef QueryTypes::Map Map;

void Compile_time_check_size_of_bufer()
{
    enum
    { 
        eMAX_SIZE_CHECK = Meta::SelectMax<bool, int, double, Str, Vec,Map>::eSIZE ,
        eSIZE_BUFER     = QueryTypes::eSIZE_BUFER,
        eIS_VALID       = eMAX_SIZE_CHECK==eSIZE_BUFER
    };
    LOKI_STATIC_CHECK(eIS_VALID, MAX_SIZE_BUFER);
}

}//namespace

void Query::Clear()
{
    switch(mType)
    {
        case eSTRING: { ((Str*)mBuf)->~basic_string(); break; }
        case eVECTOR: { ((Vec*)mBuf)->~vector();       break; }
        case eMAP:    { ((Map*)mBuf)->~map();          break; }
    }
    mType = eNULL;
}


Query::~Query(){ Clear(); }

Query::Query(): mType(eNULL){}
Query::Query(const char* src) : mType(eSTRING){ new(mBuf) Str(src);    }
Query::Query(const Query& src){ (*this)=src; }

Query& Query::operator=(const Query& src)
{
    Clear();
    mType = src.mType;
    switch(mType)
    {
        case eBOOL:   { new(mBuf) bool(src);   break; }
        case eINT:    { new(mBuf) int(src);    break; }
        case eDOUBLE: { new(mBuf) double(src); break; }
        case eSTRING: { new(mBuf) Str(src);    break; }
        case eVECTOR: { new(mBuf) Vec(src);    break; }
        case eMAP:    { new(mBuf) Map(src);    break; }
        case eNULL:   { break; }
        default:
            {
                const bool INVALID_SWITCH = true;
                assert(!INVALID_SWITCH);
            }
    }
    return *this;
}

Query& Query::operator[](const Str& key)
{
    if(mType==eNULL) (*this)=Map();
    Map& mp = *this;
    return mp[key];
}
const Query& Query::operator[](const Str& key)const
{
    const Map& mp = *this;
    Map::const_iterator it = mp.find(key);

    #ifndef RELEASE_MODE
        const bool ERROR_INVALID_KEY = it==mp.end();
        assert(!ERROR_INVALID_KEY);
    #endif
    return it->second;
}

Query& Query::operator[](const size_t index)
{
    if(mType==eNULL)
    {
        const bool ERROR_OUT_OF_RANGE = index!=0;
        assert(!ERROR_OUT_OF_RANGE);
        (*this)=Vec(1);
        Vec& tmp = *this;
        return tmp[0];
    }

    Vec& vec = *this;
    const size_t size = vec.size();

    #ifndef RELEASE_MODE
        const bool ERROR_OUT_OF_RANGE = index>size;
        assert(!ERROR_OUT_OF_RANGE);
    #endif

    if(index==size){ vec.push_back( Query() ); return vec.back();  }
    return vec[index];
}
const Query& Query::operator[](const size_t index)const
{
    const Vec& vec = *this;

    #ifndef RELEASE_MODE
        const bool ERROR_INVALID_INDEX = index>=vec.size();
        assert(!ERROR_INVALID_INDEX);
    #endif

    return vec[index];
}
#if 0
//----------------------------------------------------------------------------------
//вывод структуры в текстовом виде
const Query& Query::operator>> (Str& dst)const
{
    DefaultParser parser;
    dst = parser(*this);
    return *this;
}
Query& Query::operator>> (Str& dst)
{
    DefaultParser parser;
    dst = parser(*this);
    return *this;
}

//воссоздание собственной структуры из текстового описания
Query& Query::operator<< (const Str& dst)
{
    DefaultParser parser;
    *this = parser(dst);
    return *this;
}
//----------------------------------------------------------------------------------

#endif

//----------------------------------------------------------------------------------

Query::Iterator::~Iterator(){}

Query::Iterator::Iterator(Query* q):mQuery(q){}

//префиксная форма инкрементируется и возвращает значение
Query::Iterator& Query::Iterator::operator++() 
{
    return *this;
}   

//постфиксная форма сперва делает копию. инкрементирует оригинал, а затем возвращает копию
Query::Iterator& Query::Iterator::operator++(int)
{

    return *this;
}   
        
const Query& Query::Iterator::operator*()const{ return *mQuery;}
Query& Query::Iterator::operator*(){ return *mQuery;}

bool Query::Iterator::operator!=(const Iterator& it) const { return (*mQuery) != *(it.mQuery);}
bool Query::Iterator::operator==(const Iterator& it) const { return (*mQuery) == *(it.mQuery);}
bool Query::Iterator::IsEmpty()const { return mQuery==0; }

}//namespace Den